//------------------------------------------------------------------------------ 
// <copyright file="JDraggable.cs" company="Fm Computer">
//     Copyright (c) Fm Computer di Menatti Fulvia.  All rights reserved.
// </copyright>
//----------------------------------------------------------------------------- 
namespace FmjQuery
{
    using System.ComponentModel;
    using System.Text;
    using System.Web.UI;

    /// <summary>
    /// Draggable extender
    /// </summary>
    [ToolboxData("<{0}:JDraggable runat=server Axis=None Containment=None Cursor=_default SnapMode=both Helper=None Containment=None />")]
    [DefaultProperty("TargetControlID")]
    public class JDraggable : JQueryExtendControl
    {
        #region Fields
        #endregion

        #region Costruct
        /// <summary>
        /// Initializes a new instance of the JDraggable class.
        /// </summary>
        public JDraggable()
        {
            this.IsRenderControl = false;
        }
        #endregion

        #region Property
        /// <summary>
        /// Gets or sets id of control For a draggable with a helper specified, the matched element passed to appendTo will be used as the helper's container. If not specified, the helper is appended to the same container as the draggable
        /// </summary>
        public string IDControlAppend
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets a value indicating whether append control is client
        /// </summary>
        public bool IsClientAppendControl 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets axis
        /// </summary>
        [DefaultValue("None")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public Axis Axis
        {
            get; 
            set;
        }

        /// <summary>
        /// Gets or sets Prevents dragging if you start on elements matching the selector
        /// </summary>
        public string CancelSelector 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets A selector that matches sortable lists, for example 'div ul, ul.myclass'. If this option is used (helper must be set to clone in order to work flawlessly), a draggable can be dragged onto a sortable list and then becomes part of it
        /// </summary>
        public string ConnectToSortable 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets containment
        /// </summary>
        [DefaultValue("None")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public DragContainment Containment 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets cursor
        /// </summary>
        [DefaultValue("_default")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public WebCursor Cursor 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets position of cursor
        /// </summary>
        /// <example>
        /// top, right, bottom, left
        /// </example>
        public string CursorAt 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets time in milliseconds to define when the dragging should start. It helps preventing unwanted drags when clicking on an element
        /// </summary>
        public int Delay 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets tolerance, in pixels, for when dragging should start. If specified, dragging will not start until after mouse is dragged beyond distanc
        /// </summary>
        public int Distance 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets specified, restricts drag start click to the specified element
        /// </summary>
        public string Handler 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets allows for a helper element to be used for dragging display
        /// </summary>
        [DefaultValue("None")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public DragHelper Helper 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets a value indicating whether useful in combination with cursorAt, or in any case, if the mouse cursor is not over the helper
        /// </summary>
        /// <remarks>
        /// If set to true, overlays will be placed over all iframes on the page to prevent the iframe from capturing the mouse drag events. If a selector is supplied, the matched iframes will have an overlay placed over them
        /// </remarks>
        public bool IFrameFix 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets opacity of helper
        /// </summary>
        public float Opacity 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets a value indicating whether after drop operation object go back original position
        /// </summary>
        public bool Revert 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets the duration of the revert animation
        /// </summary>
        public int RevertDuration
        {
            get; 
            set;
        }

        /// <summary>
        /// Gets or sets used to group sets of draggable and droppable items, in addition to droppable's accept option
        /// </summary>
        public string Scope 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets a value indicating whether container auto-scrolls while dragging
        /// </summary>
        public bool AutoScroll 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets distance in pixels from the edge of the view port after which the view port should scroll
        /// </summary>
        public int ScrollSensitivity 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets value of step for horizontal resize
        /// </summary>
        public int HorizontalStep
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets a velue of step for vertical resize
        /// </summary>
        public int VerticalStep
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the speed at which the window should scroll once the mouse pointer gets within the scrollSensitivity distance
        /// </summary>
        public int ScrollSpeed 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets a value indicating whether the draggable will snap to the edges of the selected elements when near an edge of the element
        /// </summary>
        public bool Snap 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets snap mode
        /// </summary>
        [DefaultValue("both")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public DragSnapMode SnapMode 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets the distance in pixels from the snap element edges at which snapping should occur
        /// </summary>
        public int SnapTolerance 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets z-index for the helper while being dragged
        /// </summary>
        public int ZIndex 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets name of function that call when start drag operation
        /// </summary>
        public string OnClientStart 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets name of function that call when move mouse and drag element
        /// </summary>
        public string OnClientDrag 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets name of function that call when finish drag operation
        /// </summary>
        public string OnClientStop 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets Controls the z-Index of the defined group
        /// </summary>
        public string Stack 
        { 
            get; 
            set; 
        }

        /// <summary>
        /// Gets or sets minimun of zindex into group stack
        /// </summary>
        public int StatckzIndex
        {
            get; 
            set;
        }
        #endregion

        #region Overrides of JQueryExtendControl
        /// <summary>
        /// Return list of webResource
        /// </summary>
        /// <returns>web resources</returns>
        public override JWebSources GetResources()
        {
            return null;
        }

        /// <summary>
        /// Gets list of css image resources
        /// </summary>
        /// <returns>list of images</returns>
        public override CssResources GetCssResources()
        {
            return null;
        }

        /// <summary>
        /// Gets list of client nameSpace
        /// </summary>
        /// <returns>list of namespace</returns>
        public override ClientNameSpaces GetClientNameSpace()
        {
            return null;
        }

        /// <summary>
        /// Create jQuery control
        /// </summary>
        public override void CreateJControl()
        {
            if (this.Enabled)
            {
                this.Manager.Draggable = true;

                // create script
                StringBuilder builder = new StringBuilder();

                builder.AppendFormat("$('#{0}').draggable(", this.TargetControlClientID);
                builder.Append("{");
                builder.AppendFormat("cursor: '{0}'", this.Cursor);

                if (!string.IsNullOrEmpty(this.CssClass))
                {
                    builder.AppendFormat(",addClasses: '{0}'", this.CssClass);
                }

                if (!string.IsNullOrEmpty(this.IDControlAppend))
                {
                    builder.AppendFormat(",appendTo: '{0}'", this.IsClientAppendControl ? this.IDControlAppend : FindControl(this.IDControlAppend).ClientID);
                }

                if (this.Axis != Axis.None)
                {
                    builder.AppendFormat(",axis: '{0}'", this.Axis);
                }

                if (!string.IsNullOrEmpty(this.CancelSelector))
                {
                    builder.AppendFormat(",cancel: '{0}'", this.CancelSelector);
                }

                if (!string.IsNullOrEmpty(this.ConnectToSortable))
                {
                    builder.AppendFormat(",connectToSortable: '{0}'", this.ConnectToSortable);
                }

                if (this.Containment != DragContainment.None)
                {
                    builder.AppendFormat(",containment: '{0}'", this.Containment);
                }

                // cursor position
                if (!string.IsNullOrEmpty(this.CursorAt))
                {
                    string[] p = this.CursorAt.Split(',');
                    string at = string.Empty;

                    for (int x = 0; x < p.Length; x++)
                    {
                        if (x.Equals(0))
                        {
                            at += string.Concat("top: ", p[0]);
                        }
                        else
                            if (x.Equals(1))
                            {
                                at += string.Concat(",rigth: ", p[1]);
                            }
                            else
                                if (x.Equals(2))
                                {
                                    at += string.Concat(",bottom: ", p[2]);
                                }
                                else
                                {
                                    at += string.Concat(",left: ", p[3]);
                                }
                    }

                    if (!string.IsNullOrEmpty(at))
                    {
                        builder.Append("{");
                        builder.Append(at);
                        builder.Append("}");
                    }
                }

                if (this.Delay > 0)
                {
                    builder.AppendFormat(",delay: {0}", this.Delay);
                }

                if (this.Distance > 0)
                {
                    builder.AppendFormat(",distance: {0}", this.Distance);
                }

                // create grid step
                if (!this.HorizontalStep.Equals(0) && !this.VerticalStep.Equals(0))
                {
                    if (this.HorizontalStep.Equals(0) && !this.VerticalStep.Equals(0))
                    {
                        this.HorizontalStep = 1;
                    }

                    if (!this.HorizontalStep.Equals(0) && this.VerticalStep.Equals(0))
                    {
                        this.VerticalStep = 1;
                    }

                    builder.AppendFormat(",grid: [{0},{1}]", this.HorizontalStep, this.VerticalStep);
                }

                if (!string.IsNullOrEmpty(this.Handler))
                {
                    builder.AppendFormat(",handler: '{0}'", this.Handler);
                }

                if (this.Helper != DragHelper.None)
                {
                    builder.AppendFormat(",helper: '{0}'", this.Helper);
                }

                if (this.IFrameFix)
                {
                    builder.Append(",iframeFix: true");
                }

                if (!this.Opacity.Equals(0.0f))
                {
                    builder.AppendFormat(",opacity: {0}", this.Opacity.ToString().Replace(",", "."));
                }

                if (this.Revert)
                {
                    builder.Append(",revert: true");

                    if (this.RevertDuration > 0)
                    {
                        builder.AppendFormat("revertDuration: {0}", this.RevertDuration);
                    }
                }

                // scroll option
                if (this.AutoScroll)
                {
                    builder.Append(",scroll: true");

                    if (this.ScrollSensitivity > 0)
                    {
                        builder.AppendFormat(",scrollSensitivity: {0}", this.ScrollSensitivity);
                    }

                    if (this.ScrollSpeed > 0)
                    {
                        builder.AppendFormat(",scrollSpeed: {0}", this.ScrollSpeed);
                    }
                }

                // snap option
                if (this.Snap)
                {
                    builder.Append(",snap: true");
                    builder.AppendFormat(",snapMode: '{0}'", this.SnapMode);

                    if (this.SnapTolerance > 0)
                    {
                        builder.AppendFormat(",snapTolerance: {0}", this.SnapTolerance);
                    }
                }

                if (this.ZIndex > 0)
                {
                    builder.AppendFormat(",zIndex: {0}", this.ZIndex);
                }

                if (!string.IsNullOrEmpty(this.Stack))
                {
                    string g = string.Format("group: '{0}'", this.Stack);

                    if (this.StatckzIndex > 0)
                    {
                        g += string.Concat(",min: ", this.StatckzIndex);
                    }

                    builder.Append(",stack: {");
                    builder.Append(g);
                    builder.Append("}");
                }

                if (!string.IsNullOrEmpty(this.OnClientStart))
                {
                    builder.AppendFormat(",start: {0}", this.OnClientStart);
                }

                if (!string.IsNullOrEmpty(this.OnClientDrag))
                {
                    builder.AppendFormat(",drag: {0}", this.OnClientDrag);
                }

                if (!string.IsNullOrEmpty(this.OnClientStop))
                {
                    builder.AppendFormat(",stop: {0}", this.OnClientStop);
                }

                builder.Append("});");

                Utility.RegisterStartUpScript(this.Page, string.Concat("Drag_", this.ClientID), builder.ToString());
            }
        }
        #endregion
    }
}